package com.dmai.aiet.epc.archive.service.impl;

import com.dmai.aiet.epc.archive.exception.BusinessException;
import com.dmai.aiet.epc.archive.pojo.vo.*;
import com.dmai.aiet.epc.archive.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


@Service
public class StudyServiceImpl implements StudyService {

    @Autowired
    private CourseStudyRecordsService courseStudyRecordsService;

    @Autowired
    private SpecialTopicStudyRecordsService specialTopicStudyRecordsService;

    @Autowired
    private SpecialTopicClassStudyRecordsService specialTopicClassStudyRecordsService;

    @Autowired
    private ExamStudyRecordsService examStudyRecordsService;

    @Autowired
    private CertificationStudyRecordsService certificationStudyRecordsService;

    @Autowired
    private OfflineClassStudyRecordsService offlineClassStudyRecordsService;


    // TODO 待补充认证、面授班、考试等时长统计
    // 考试：参加3次考试，每次考试限时50分钟，则统计50*3=150分钟时长
    // 认证：取主办方结束时间-主办方开始时间。
    // 课程、专题 不一定要学完， 学习中有时长的都统计。  专题实在不好弄就不统计
    // 课程学习中的跨天的，如果归档数据不满足的话，可能要批注下，
    // 培训班可以算学时， 学习时长有难度
    @Override
    @Cacheable(value = "archives_aggregate", key = "#userid")
    public LearningAggregateVo getAggregate(String userid) {
        LearningAggregateVo result = new LearningAggregateVo();
        LearningAggregateVo course = courseStudyRecordsService.getAggregate(userid);
        LearningAggregateVo specialTopic = specialTopicStudyRecordsService.getAggregate(userid);
        LearningAggregateVo specialTopicClass = specialTopicClassStudyRecordsService.getAggregate(userid);
        LearningAggregateVo exam = examStudyRecordsService.getAggregate(userid);
        LearningAggregateVo offlineClass = offlineClassStudyRecordsService.getAggregate(userid);

        result.setCourseCount(course.getCourseCount() + specialTopic.getCourseCount() + specialTopicClass.getCourseCount() + exam.getCourseCount() + offlineClass.getCourseCount());
        result.setCreditHours(course.getCreditHours().add(specialTopic.getCreditHours()).add(specialTopicClass.getCreditHours()).add(exam.getCreditHours()).add(offlineClass.getCreditHours()));
        result.setLearningHours(course.getLearningHours().add(specialTopic.getLearningHours()).add(specialTopicClass.getLearningHours()).add(exam.getLearningHours()).add(offlineClass.getLearningHours()));

        return result;
    }

    @Override
    @Cacheable(value = "archives_stat", key = "#userid+'_'+#axle+'_'+#startStamp+'_'+#endStamp")
    public LearningStatVo getStat(String userid, Integer axle, Long startStamp, Long endStamp) {
        LocalDate date1 = LocalDate.ofEpochDay(startStamp / (24 * 60 * 60 * 1000));
        LocalDate date2 = LocalDate.ofEpochDay(endStamp / (24 * 60 * 60 * 1000));

        long daysDiff = ChronoUnit.DAYS.between(date1, date2);
        if (daysDiff > 366) {
            throw new BusinessException("超过最大区间限制");
        }

        LearningStatVo result = new LearningStatVo();

        List<LearningStatItem> course = courseStudyRecordsService.getStat(userid, axle, startStamp, endStamp);
        List<LearningStatItem> specialTopic = specialTopicStudyRecordsService.getStat(userid, axle, startStamp, endStamp);
        List<LearningStatItem> specialTopicClass = specialTopicClassStudyRecordsService.getStat(userid, axle, startStamp, endStamp);
        List<LearningStatItem> exam = examStudyRecordsService.getStat(userid, axle, startStamp, endStamp);
        result.setCourse(course);
        result.setSpecialTopic(specialTopic);
        result.setSpecialTopicClass(specialTopicClass);
        result.setExam(exam);

        BigDecimal courseTotal = course.stream()
                .map(LearningStatItem::getLearningHours)
                .filter(Objects::nonNull)
                .reduce((a, b) -> a.add(b)).orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);

        BigDecimal specialTopicTotal = specialTopic.stream()
                .map(LearningStatItem::getLearningHours)
                .filter(Objects::nonNull)
                .reduce((a, b) -> a.add(b)).orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);

        BigDecimal specialTopicClassTotal = specialTopicClass.stream()
                .map(LearningStatItem::getLearningHours)
                .filter(Objects::nonNull)
                .reduce((a, b) -> a.add(b)).orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);

        BigDecimal examTotal = exam.stream()
                .map(LearningStatItem::getLearningHours)
                .filter(Objects::nonNull)
                .reduce((a, b) -> a.add(b)).orElse(BigDecimal.ZERO).setScale(2, BigDecimal.ROUND_HALF_UP);

        result.setLearningHours(courseTotal.add(specialTopicTotal).add(specialTopicClassTotal).add(examTotal));

        return result;
    }

    @Override
    @Cacheable(value = "archives_certificate", key = "#userid+'_'+#category")
    public LearningCertificateVo getCertificate(String userid, String category, Integer limit) {
        LearningCertificateVo result = new LearningCertificateVo();

        List<LearningCertificateItem> list = new ArrayList<>();
        switch (category) {
            case "course":
                list = courseStudyRecordsService.getCertificate(userid);
                break;

            case "specialTopic":
                list = specialTopicStudyRecordsService.getCertificate(userid);
                break;

            case "specialTopicClass":
                list = specialTopicClassStudyRecordsService.getCertificate(userid);
                break;

            case "exam":
                list = examStudyRecordsService.getCertificate(userid);
                break;

            case "offlineClass":
                list = offlineClassStudyRecordsService.getCertificate(userid);
                break;

            case "certification":
                list = certificationStudyRecordsService.getCertificate(userid);
                break;

            default:
                list.addAll(certificationStudyRecordsService.getCertificate(userid));
                list.addAll(offlineClassStudyRecordsService.getCertificate(userid));
                list.addAll(examStudyRecordsService.getCertificate(userid));
                list.addAll(specialTopicClassStudyRecordsService.getCertificate(userid));
                list.addAll(specialTopicStudyRecordsService.getCertificate(userid));
                list.addAll(courseStudyRecordsService.getCertificate(userid));

                break;

        }

        result.setList(list);
        result.setCount(list.size());

        return result;
    }
}
